
#include <stdio.h>
#include <system/application.h>
#include <graphics/sprite.h>
#include <maths/vector2.h>
#include <maths/vector3.h>
#include <vector>
#include <graphics/mesh_instance.h>
#include <graphics/vita/texture_vita.h>
#include <graphics/model.h>

#include "GameState.h"
#include "PlayState.h"


PlayState::PlayState(const abfw::Platform& platform): shootTimer(0), mTurretCardVisible(true)
{
	mFont = new abfw::Font();
	mFont->Load("comic_sans", platform);
	
	mInputManager = platform.CreateSonyControllerInputManager();

	//-- Load all required 3D models
	mObjLoader.Load("enemy.obj", platform, mEnemyMesh);
	mObjLoader.Load("m.obj", platform, *mPlayer.GetModel());
	mObjLoader.Load("bullet.obj", platform, mBulletModel);
	mObjLoader.Load("base.obj", platform, mBaseModel);

	mEnemyManager.AddEnemy(mEnemyMesh.mesh(),*mARCardTransforms[0]);

	for (int i = 0; i < 6; i++)
	mBase[i].Init(mBaseModel.mesh());

	mPlayer.Init(mPlayer.GetModel()->mesh());
	mPlayer.SetOrigin(*mARCardTransforms[0]);
	mPlayer.SetLocalScale(abfw::Vector3(0.005195f, 0.005195f, 0.005195f));

}

PlayState::~PlayState()
{
	mEnemyManager.CleanUp();
	//-- create player clean up function
	delete mPlayer.mesh();

	delete mInputManager;
	mInputManager = NULL;

	mPlayerGun.CleanUpBullets();
}

GameStates::State PlayState::Update() 
{
	
	if (mARCardFound[0] == false)
	{
		return GameStates::MARKERLOSTSTATE;
	}

	if (GameLost())
	{
		return GameStates::GAMEOVERSTATE;
	}

	abfw::Matrix44 scale;
	scale.Scale(abfw::Vector3(0.00199,0.00199,0.00199));

	//-- Update all marker transforms
	for (int i = 0; i < 6; i++)
	{
		//-- If the current marker is found
		if(sampleIsMarkerFound(i))
		{			
			mBase[i].SetTransform(scale * *mARCardTransforms[i]);
		}
	}
	
	// update the main game

	//update input
	mInputManager->Update();

	// give option to reset position
	if (mInputManager->buttons_pressed() & ABFW_SONY_CTRL_CROSS)
			{
				// Reset player position
				mPlayer.Reset();
			}
			else
			{
				// update player
				mPlayer.Update(mInputManager, *mARCardTransforms[0]);

				// player shooting
				if (mInputManager->buttons_down() & ABFW_SONY_CTRL_R2)
				{
					mPlayerGun.Fire(mPlayer.GetPlayerRotate().z, mBulletModel.mesh(), mPlayer.GetLocalTranslation() * *mARCardTransforms[0]);
				}
				// update (move, collision check and cleanup) bullets in player gun
				mPlayerGun.UpdateBullets(&mEnemyManager, &mPlayer);


				// Powerups (turrets)
				// iterate through
				for ( std::vector<Turret>::iterator turret = mCurrentTurrets.begin(); turret != mCurrentTurrets.end(); turret++ )
				{
					
					// check if in range and can fire		
					if (turret->CanFire() == true)
					{
						// add a bullet to gun
						turret->GetGun()->Fire(turret->GetRotationZ(),mBulletModel.mesh() ,*mARCardTransforms[turret->GetAssignedMarker()]);
					}
					// update (rotate towards closest in range enemy and set transform)
					turret->Update(*mARCardTransforms[turret->GetAssignedMarker()],*mARCardTransforms[0], mEnemyManager.GetEnemies());
					// update bullets
				
					turret->GetGun()->UpdateBullets(&mEnemyManager, &mPlayer);
				}

				// update all enemies
				mEnemyManager.Update(*mARCardTransforms[0], mPlayer.GetPlayerMove(), &mPlayer);	
				
				
				// change this
				bool cardUseable = false;
				for (int i = 1; i < 6; i++)
				{
					if (mARCardFound[i] && !mARCardInUse[i])
					{
						cardUseable = true;
					}
				}
			
				if (cardUseable )
				{
					mTurretCardVisible = true;
					if (mPlayer.IsPowerupAvailable() && mInputManager->buttons_pressed() & ABFW_SONY_CTRL_SQUARE)
					{
						// add powerup
						Turret turret;
						turret.Init(mPlayer.GetModel()->mesh());
					
						//-- Set assigned marker to the first free marker
						turret.SetAssignedMarker(mTurretMgr.AssignMarker(mARCardFound, mARCardInUse));
						mARCardInUse[turret.GetAssignedMarker()] = true;
						mCurrentTurrets.push_back(turret);

						mPlayer.SetPowerupAvailable(false);
						mPlayer.ResetPowerlevel();

						//-- Reduce the amount of power recieved from enemies
						if (mPlayer.GetCurrentPowerUpAmount() > 5)
						mPlayer.SetCurrentPowerUpAmount(mPlayer.GetCurrentPowerUpAmount()/2);
					}

				}
				else
				{
					//-- print no turret card visible
					if (mPlayer.IsPowerupAvailable() && mInputManager->buttons_pressed() & ABFW_SONY_CTRL_SQUARE)
					{
						mTurretCardVisible = false;
					}
					
				}
				

			}
	return GameStates::PLAYSTATE;

}

int PlayState::GetPlayerScore()
{
	return mEnemyManager.GetEnemiesDead();
}

bool PlayState::GameLost()
{
	//-- If the player is dead, the game is lost
	if (mPlayer.GetHealth() <= 0)
	{
		return true;
	}
	else
	{
		return false;
	}
}
void PlayState::Draw2D(abfw::SpriteRenderer* render, abfw::Matrix44 Projection) 
{

	if(mFont)
	{
		mFont->RenderText(render, abfw::Vector3(850.0f, 510.0f, 1.0f), 1.0f, 0xffffffff, abfw::TJ_LEFT, "FPS: %.1f", mFps);
		mFont->RenderText(render, abfw::Vector3(0.0f, 0.0f, 1.0f), 1.0f, 0xff0000ff, abfw::TJ_LEFT, "Player Health = %.0f", mPlayer.GetHealth());
		mFont->RenderText(render, abfw::Vector3(0.0f, 30.0f, 1.0f), 1.0f, 0xffffffff, abfw::TJ_LEFT, "Power Level = %i%", mPlayer.GetPowerLevel());

		if (mPlayer.IsPowerupAvailable())
			mFont->RenderText(render, abfw::Vector3(0.0f, 60.0f, 1.0f), 1.0f, 0xff0000ff, abfw::TJ_LEFT, "Place any maker and press SQUARE to spawn support!");

		if (mTurretCardVisible == false)
			mFont->RenderText(render, abfw::Vector3(0.0f, 90.0f, 1.0f), 1.0f, 0xff0000ff, abfw::TJ_LEFT, "NO TURRET CARD VISIBLE!");

		mPlayer.DrawHud(render);
	}

}
void PlayState::Draw3D(abfw::Renderer3D* render, abfw::Colour defaultColour) 
{
	
	mEnemyManager.Draw(render, defaultColour);
	//-- red glow for ship
	render->default_shader_data().set_ambient_light_colour(abfw::Colour(1,0,0,0));
	mPlayer.Draw(render);
	render->default_shader_data().set_ambient_light_colour(defaultColour);
	mPlayerGun.DrawBullets(render);

	//-- draw turrets and bullets
	for ( std::vector<Turret>::iterator mTurretIterator = mCurrentTurrets.begin(); mTurretIterator != mCurrentTurrets.end(); ++mTurretIterator )
	{
		mTurretIterator->GetGun()->DrawBullets(render);
		mTurretIterator->Draw(render);
	}

	//-- draw bases on visible markers
	for (int i = 0; i < 6; i++)
	{
		if (mARCardFound[i])
		{
			render->DrawMesh(mBase[i].GetMeshInstance());
		}
	}

}
